package cn.itcast.zt.endpoint;

import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangtian105
 * @ClassName FunctionalEndpoint.java
 * @projectName SpringBoot2.x
 * @Description 端点
 * @createTime 2020年05月19日 14:16:00
 */
@Slf4j
@Component
public class FunctionalEndpoint {
    public Mono<ServerResponse> index(ServerRequest serverRequest) {

        val headers = serverRequest.headers();
        val httpMethod = serverRequest.method();
        val methodName = serverRequest.methodName();
        val cookies = serverRequest.cookies();
        val params = serverRequest.queryParams();
        val stringStringMap = serverRequest.pathVariables();
        val httpServletRequest = serverRequest.path();
        val uri = serverRequest.uri();
        val principal = serverRequest.principal();
        val inetSocketAddress = serverRequest.remoteAddress();

        log.info("headers:{}", headers);
        log.info("httpMethod:{}", httpMethod);
        log.info("methodName:{}", methodName);
        log.info("cookies:{}", cookies);
        log.info("params:{}", params);
        log.info("stringStringMap:{}", stringStringMap);
        log.info("httpServletRequest:{}", httpServletRequest);
        log.info("uri:{}", uri);
        log.info("principal:{}", principal);
        log.info("inetSocketAddress:{}", inetSocketAddress);

        Map<String, String> map = new HashMap<>() ;
        map.put("name", "zhangtian") ;
        return ServerResponse.ok().bodyValue(Collections.unmodifiableMap(map));
    }

    public Mono<ServerResponse> me(ServerRequest serverRequest) {
        val stringObjectHashMap = new HashMap<String, Object>();
        stringObjectHashMap.put("id", 1);
        stringObjectHashMap.put("username", 123);

        return ServerResponse.ok().bodyValue(stringObjectHashMap);
    }

    /*
     * 传参是json格式，body中赋值
        {
          "name": "zhangsan",
          "age": 18
        }
     * 请求头部格式：Content-Type:application/json
     */
    public Mono<ServerResponse> postJson(ServerRequest serverRequest) {
        // 接收json数据 0..1数据 返回的是对象
        val bodyToMono = serverRequest.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
        });

        // 0..N数据  返回的是数组
        /*val bodyToFlux = serverRequest.bodyToFlux(new ParameterizedTypeReference<Map<String, Object>>() {
        });*/

        return ServerResponse.ok().body(bodyToMono, Map.class);
    }

    // 请求头部格式：Content-Type:application/x-www-form-urlencoded
    // 需要在表单中录入数据
    // WebFlux 官方文档中提到, formdata数据来自于 application/x-www-form-urlencoded, 所以使用以上方式实现 form data 参数绑定的, 注意了, 提交方式一定为: application/x-www-form-urlencoded, 否则, 请使用 request body
    public Mono<ServerResponse> postForm(ServerRequest serverRequest) {
        // 接收form表单数据
        val bodyToMono = serverRequest.bodyToMono(new ParameterizedTypeReference<MultiValueMap<String, String>>() {
        }) ;

        return ServerResponse.ok().body(bodyToMono, MultiValueMap.class);
    }

    /** 重定向 */
    public Mono<ServerResponse> redirect(ServerRequest serverRequest) {
        // 重定向到 /
        val path = serverRequest.uriBuilder().replacePath("/");
        URI build = path.build();
        return ServerResponse.status(HttpStatus.FOUND).location(build).build();
    }
}
